<?php

/**
 * MyHammer IndexedMemcache
 *
 * LICENSE
 *
 * This source file is subject to the GNU General Public License Version 3
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.myhammer.de/opensource/license/gpl.txt
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to opensource@myhammer.de so we can send you a copy immediately.
 *
 * @category   MyHammer
 * @package    MyHammer_IndexedMemcache
 * @subpackage Memcache
 * @license    http://www.myhammer.de/opensource/license/gpl.txt GNU General Public License Version 3
 * @version    1.0
 * @author     Steven Berg <berg@myhammer.de>
 */

class cMemCacheIndex {

    /**
     * create index and save this for memCacheModel
     *
     * @param cMemCacheModel $oMemCacheModel
     * @return boolean
     */
    public static function saveIndex(cMemCacheModel $oMemCacheModel) {
        $iLinkId = $oMemCacheModel->getLinkId();
        if ($iLinkId === 0) {
            return false;
        }

        $aColumns = $oMemCacheModel->getColumns();
        foreach ($aColumns as $sColumnName => $mColumnValue) {
            // create columnprefix
            $sColumnPrefix = self::createColumnPrefix($oMemCacheModel, $sColumnName);

            // create index for columnvalue
            $aColumnIndex = self::createIndexArrayForColumnValue($mColumnValue);

            if (count($aColumnIndex) > 0) {
                foreach ($aColumnIndex as $iPosition => $sCharacter) {
                    // create key for this character
                    $sIndexKey = self::createIndexKey($sColumnPrefix, $sCharacter, $iPosition);

                    // read index for indexkey
                    $aIndexFilesFromMemCache = cMemCache::read($sIndexKey);
                    if (!is_array($aIndexFilesFromMemCache)) {
                        $aIndexFilesFromMemCache = array();
                    }

                    // set linkId to the index
                    $aIndexFilesFromMemCache[$iLinkId] = null;

                    // save new index
                    cMemCache::write($sIndexKey, $aIndexFilesFromMemCache);
                }
            }
        }

        return true;
    }

    /**
     * create Prefix for Column
     *
     * @param cMemCacheModel $oMemCacheModel
     * @param string $sColumnName
     * @return string
     *
     * @example
     *  input:
     *      $oMemCacheModel = class 'cTestModel'
     *      $sColumnName    = 'username';
     *
     *  output:
     *      cTestModel|v1|username|
     *
     */
    private static function createColumnPrefix(cMemCacheModel $oMemCacheModel, $sColumnName) {
        return $oMemCacheModel->getClassName() . '|' . cConfigMemCache::IDENTIFIER_CACHE_VERSION . '|' . $sColumnName . '|';
    }

    /**
     * create key for current character
     *
     * @param string $sColumnPrefix
     * @param string $sCharacter
     * @param int $iPosition
     * @return string
     *
     * @example
     *  input:
     *      $sColumnPrefix  = 'cTestModel|v1|username|'
     *      $sCharacter     = 's'
     *      $iPosition      = 0
     *
     *  output:
     *      cTestModel|v1|username|s(0)
     *
     */
    private static function createIndexKey($sColumnPrefix, $sCharacter, $iPosition) {
        return $sColumnPrefix . $sCharacter . '(' . $iPosition . ')';
    }

    /**
     * create IndexArray of ColumnValue
     *
     * @param mixed $mColumnValue
     * @return array
     *
     * @example
     *  input:
     *      $mColumnValue = steven
     *
     *  output:
     *      0 => t
     *      1 => e
     *      2 => s
     *      3 => t
     *      4 => e
     *      5 => r
     */
    private static function createIndexArrayForColumnValue($mColumnValue) {
        $aValue = array();

        $iValueLength = strlen($mColumnValue);
        for ($i = 0; $i < $iValueLength; $i++) {
            $aValue[$i] = strtolower(substr($mColumnValue, $i, 1));
        }

        return $aValue;
    }


    /**
     * get LinkIds for SearchValue
     *
     * @param cMemCacheModel $oMemCacheModel
     * @param string $sColumnName
     * @param string $sSearchValue
     * @return array
     */
    public static function getLinkIdsForSearchValue(cMemCacheModel $oMemCacheModel, $sColumnName, $sSearchValue) {
        $sColumnPrefix = self::createColumnPrefix($oMemCacheModel, $sColumnName);

        $aSearchIndex = self::createIndexArrayForColumnValue($sSearchValue);

        return self::getLinkIdsBySearchIndexArray($aSearchIndex, $sColumnPrefix);
    }

    /**
     * get LinkIds for SearchIndex
     *
     * @param cMemCacheModel $oMemCacheModel
     * @param string $sColumnName
     * @param array $aSearchIndex
     * @return array
     */
    public static function getLinkIdsForSearchIndex(cMemCacheModel $oMemCacheModel, $sColumnName, $aSearchIndex) {
        $sColumnPrefix = self::createColumnPrefix($oMemCacheModel, $sColumnName);

        return self::getLinkIdsBySearchIndexArray($aSearchIndex, $sColumnPrefix);
    }

    /**
     * get LinkIds for SearchIndex and Column
     *
     * @param array $aSearchIndex
     * @param string $sColumnPrefix
     * @return array
     *
     *   ['0'] = string(1)  "t"
     *   ['1'] = string(1)  "e"
     *   ['2'] = string(1)  "s"
     *   ['3'] = string(1)  "t"
     *
     */
    private static function getLinkIdsBySearchIndexArray($aSearchIndex, $sColumnPrefix) {
        //cVardump::dump($aSearchIndex, 'SearchIndexArray lautet');
        $aFoundLinkIds = array();
        foreach ($aSearchIndex as $iPosition => $sCharacter) {
            $sIndexKey = self::createIndexKey($sColumnPrefix, $sCharacter, $iPosition);

            $aMemCacheResult = cMemCache::read($sIndexKey);
            if (is_array($aMemCacheResult)) {
                // found character
                foreach ($aMemCacheResult as $sLinkId => $sNull) {
                    if (!array_key_exists($sLinkId, $aFoundLinkIds)) {
                        $aFoundLinkIds[$sLinkId] = 1;
                    } else {
                        $aFoundLinkIds[$sLinkId] = $aFoundLinkIds[$sLinkId] + 1;
                    }
                }
            }
        }
        return $aFoundLinkIds;
    }
}